﻿using System;
using System.IO.Ports;
using System.Threading;

namespace TestFireBroadcastingHostPhone.Product
{
    public class Productions
    {
        /// <summary>
        /// 产品通讯波特率
        /// </summary>
        public const int product_baudrate = 4800;
        /// <summary>
        /// 产品通讯串口
        /// </summary>
        private protected SerialPort ? CommunicatePort;
        /// <summary>
        /// 广播音源板相关指令
        /// </summary>
        internal struct ProductCommunicate_Struct
        {
            /// <summary>
            /// 帧头
            /// </summary>
            public const byte FrameHeader = 0x68;//帧头
            /// <summary>
            /// 帧尾
            /// </summary>
            public const byte FrameFailure = 0x16;//帧尾
            /// <summary>
            /// 命令/功能码
            /// </summary>
            public enum ProductCmd : byte
            {
                /// <summary>
                /// 应急控制
                /// </summary>
                EmergencyControl = 0,
                /// <summary>
                /// 消音控制
                /// </summary>
                Silence_Control = 6,
                /// <summary>
                /// 查询自动模式
                /// </summary>
                Query_AutoMode = 12,
                /// <summary>
                /// 屏蔽区域控制显示
                /// </summary>
                ShieldAreaContorlDisplay = 14,
                /// <summary>
                /// 自检
                /// </summary>
                CheckSelf = 15,
                /// <summary>
                /// 广播主机复位
                /// </summary>
                HostReset = 20,
                /// <summary>
                /// 查询功放主电/备电/输出信息
                /// </summary>
                Query_AmplifierInfo = 21,
                /// <summary>
                /// 更改广播主机通讯波特率
                /// </summary>
                ResetProductBaudrate = 22,
                /// <summary>
                /// 进入刷音源字库模式
                /// </summary>
                EnterUpdateVoiceSource = 23,
                /// <summary>
                /// 音源板刷字库
                /// </summary>
                UpdateVoiceSource = 24,
                /// <summary>
                /// 退出音源板刷字库
                /// </summary>
                ExitUpdateVoiceSource = 25,
                /// <summary>
                /// 注册功放
                /// </summary>
                RegisterAmplifier = 26,
                /// <summary>
                /// 查询注册功放
                /// </summary>
                Query_RegisterAmplifier = 27,
                /// <summary>
                /// 屏蔽注册功放
                /// </summary>
                Shield_RegisterAmplifier = 28,
                /// <summary>
                /// 查询音源板地址
                /// </summary>
                Query_AmplifierAddress = 30,
                /// <summary>
                /// 设置音源板地址
                /// </summary>
                Set_AmplifierAddress = 31,
                /// <summary>
                /// 播放U盘中音频文件
                /// </summary>
                Display_Videos = 34,
                /// <summary>
                /// 按键检测
                /// </summary>
                Key_Check = 35,
                /// <summary>
                /// 播放/暂停录音
                /// </summary>
                Display_Redio = 36,
                /// <summary>
                /// 删除录音
                /// </summary>
                Delete_Redio = 37,
                /// <summary>
                /// 调节监听音量
                /// </summary>
                Adjust_MornitorVolume = 38,
                /// <summary>
                /// 查询话筒状态
                /// </summary>
                Query_MicroPhoneStatus = 39,
            }
        }
        /// <summary>
        /// 应急状态
        /// </summary>
        public enum EmergencyStatus : byte
        {
            /// <summary>
            /// 应急停止
            /// </summary>
            Stop = 0,
            /// <summary>
            /// 应急暂停
            /// </summary>
            Suspend = 1,
            /// <summary>
            /// 应急开始
            /// </summary>
            Start = 2,
            /// <summary>
            /// 应急继续
            /// </summary>
            Continue = 3,
        }

        #region -- 公共函数
        /// <summary>
        /// 串口数据发送
        /// </summary>
        /// <param name="send_data">发送数据</param>
        /// <param name="errinfo">错误信息</param>
        public void SendData(byte[] send_data, out string errinfo)
        {
            errinfo = string.Empty;
            if (CommunicatePort is null)
            {
                errinfo = "未配置串口!";
                return;
            }
            try
            {
                if (!CommunicatePort.IsOpen)
                {
                    CommunicatePort.Open();
                }
                if (!string.IsNullOrEmpty(CommunicatePort.PortName) && CommunicatePort.IsOpen)
                {
                    CommunicatePort.ReadExisting();                          //发送前清缓冲区
                    CommunicatePort.Write(send_data, 0, send_data.Length);
                }
                else
                {
                    errinfo = "串口未打开，无法发送数据";
                }
            }
            catch (Exception ex)
            {
                errinfo = "发送数据出现错误" + ex;
            }
        }
        /// <summary>
        /// 等待串口数据接收
        /// </summary>
        /// <param name="wait_timer">串口超时等待时间</param>
        /// <param name="setting_lenth">串口接收数据长度</param>
        public byte[] Receive_Wait(int wait_timer, int setting_lenth, out string err_info)
        {
            int data_lenth = 0;
            byte[] receive_data = new byte[setting_lenth];
            err_info = string.Empty;
            if (CommunicatePort is null)
            {
                err_info = "未配置串口!";
                return receive_data;
            }
            try
            {
                for (int b = 0; b < wait_timer; b++)   //最长等待500ms
                {
                    Thread.Sleep(10);                  //等待10ms
                    data_lenth = CommunicatePort.BytesToRead;   //获取接收数据长度
                    if (data_lenth >= setting_lenth) break;       //避开接收异常，如上电断电引起的0X00
                }
                if (data_lenth == setting_lenth)
                {
                    Array.Resize(ref receive_data, data_lenth);               //重定义数组长度
                    CommunicatePort.Read(receive_data, 0, data_lenth);      //读取数据
                    if (receive_data[0] == ProductCommunicate_Struct.FrameHeader || receive_data[^1] == ProductCommunicate_Struct.FrameFailure)
                    {
                        if (receive_data[^2] != Check_Sum_Cal(receive_data))
                        {
                            err_info = "数据校验错误";
                        }
                    }
                    else
                    {
                        err_info = "数据接收错误";
                    }
                }
                else
                {
                    err_info = "未接收到指定数据";
                }
            }
            catch (Exception ex)
            {
                err_info = $"Error reading data: {ex.Message}";
            }
            return receive_data;
        }
        /// <summary>
        /// 产品通讯校验和计算
        /// </summary>
        /// <param name="input_data">输入数据</param>
        /// <returns>返回结果</returns>
        private static byte Check_Sum_Cal(byte[] input_data)
        {
            byte result = 0;
            int sum = 0;
            for (int a = 4; a < input_data.Length - 2; a++)
            {
                sum += input_data[a];
            }
            result = (byte)sum;
            return result;
        }
        #endregion

        #region -- 数据填充

        /// <summary>
        /// 广播主机复位数据填充
        /// </summary>
        /// <returns></returns>
        public byte[] DisPlay_vHostPhoneReset()
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.HostReset;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = 0;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 广播主机查询自动模式
        /// </summary>
        /// <returns></returns>
        public byte[] Display_vQueryAutoMode()
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Query_AutoMode;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = 0;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }

        /// <summary>
        /// 应急控制状态数据填充
        /// </summary>
        /// <param name="status">应急状态</param>
        /// <returns></returns>
        public byte[] Display_vEmergency_Control(EmergencyStatus status)
        {
            byte[] send_cmd = new byte[8];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.EmergencyControl;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 2;
            send_cmd[4] = (byte)status;//应急状态
            send_cmd[5] = 0;//单次应急：不用循环应急
            send_cmd[6] = Check_Sum_Cal(send_cmd);
            send_cmd[7] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }

        /// <summary>
        /// 消音控制数据填充
        /// </summary>
        /// <returns></returns>
        public byte[] Display_vSilence_Control()
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Silence_Control;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = 1;//开启消音
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }

        /// <summary>
        /// 自检控制数据填充
        /// </summary>
        /// <param name="time">自检时间3-20s</param>
        /// <returns></returns>
        public byte[] Display_vCheckSelf(byte time)
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.CheckSelf;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = time;//自检时间
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }

        /// <summary>
        /// 查询功放主/备电，输出状态
        /// </summary>
        /// <param name="address">功放地址</param>
        /// <returns></returns>
        public byte[] Display_vQueryAmplifier(byte address)
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Query_AmplifierInfo;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = address;//功放地址
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 屏蔽注册功放
        /// </summary>
        /// <param name="status">屏蔽：0x03,释放：0x00</param>
        /// <returns></returns>
        public byte[] Shield_RegisterAmplifier(byte status)
        {
            byte[] send_cmd = new byte[12];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Shield_RegisterAmplifier;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 6;//数据长度
            send_cmd[4] = 0x00;//起始地址
            send_cmd[5] = 0x14;//结束地址
            send_cmd[6] = 0;
            send_cmd[7] = 0;
            send_cmd[8] = 0;
            send_cmd[9] = status;//屏蔽一个攻放
            send_cmd[10] = Check_Sum_Cal(send_cmd);
            send_cmd[11] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }

        /// <summary>
        /// 屏蔽区域控制显示
        /// </summary>
        /// <param name="status">是否屏蔽：0x00,屏蔽；0x02，打开</param>
        /// <returns></returns>
        public byte[] Display_vShieldAreaContorlDisplay(byte status)
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.ShieldAreaContorlDisplay;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = status;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }

        /// <summary>
        /// 注册功放
        /// </summary>
        /// <param name="number">注册功放的数量</param>
        /// <returns></returns>
        public byte[] Display_vRegisterAmplifier(byte number)
        {
            byte[] send_cmd = new byte[12];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.RegisterAmplifier;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 6;//数据长度
            send_cmd[4] = 0x00;//起始地址
            send_cmd[5] = 0x14;//结束地址
            send_cmd[6] = 0;
            send_cmd[7] = 0;
            send_cmd[8] = 0;
            send_cmd[9] = number;//注册两个攻放
            send_cmd[10] = Check_Sum_Cal(send_cmd);
            send_cmd[11] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 查询注册功放
        /// </summary>
        /// <returns></returns>
        public byte[] Display_vQuery_RegisterAmplifier()
        {
            byte[] send_cmd = new byte[8];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Query_RegisterAmplifier;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 2;//数据长度
            send_cmd[4] = 0;//起始地址
            send_cmd[5] = 1;//结束地址
            send_cmd[6] = Check_Sum_Cal(send_cmd);
            send_cmd[7] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 查询主机地址
        /// </summary>
        /// <returns></returns>
        public byte[] Display_vQuery_AmplifierAddress()
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Query_AmplifierAddress;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = 0;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 设置主机地址
        /// </summary>
        /// <param name="address">地址1-255</param>
        /// <returns></returns>
        public byte[] Display_vSet_AmplifierAddress(byte address)
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Set_AmplifierAddress;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = address;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 进入播放U盘文件界面
        /// </summary>
        /// <param name="data">声音大小</param>
        /// <returns></returns>
        public byte[] Display_vEntryDisplayVideos(byte data)
        {
            byte[] send_cmd = new byte[8];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Display_Videos;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 2;
            send_cmd[4] = 0xff;
            send_cmd[5] = data;
            send_cmd[6] = Check_Sum_Cal(send_cmd);
            send_cmd[7] = ProductCommunicate_Struct.FrameFailure;

            return send_cmd;
        }

        /// <summary>
        /// 播放U盘音频文件
        /// </summary>
        /// <param name="data">播放音频路径</param>
        /// <param name="status">播放状态：00停止，01播放</param>
        /// <returns></returns>
        public byte[] Display_vDisplayVideos(byte data, bool status)
        {
            byte[] send_cmd = new byte[8];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Display_Videos;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 2;
            send_cmd[4] = data;
            if (send_cmd[4] == 0xff)
            {
                send_cmd[5] = 0x20;
            }
            else
            {
                if (status) send_cmd[5] = 0x01;
                else send_cmd[5] = 0x00;
            }
            send_cmd[6] = Check_Sum_Cal(send_cmd);
            send_cmd[7] = ProductCommunicate_Struct.FrameFailure;

            return send_cmd;
        }
        /// <summary>
        /// 按键检测命令数据填充
        /// </summary>
        /// <returns></returns>
        public byte[] Display_vKeyCheck()
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Key_Check;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = 1;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 进入音源板刷字库的数据填充
        /// </summary>
        /// <returns></returns>
        public byte[] Display_vEnterUpdateVoiceSource()
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.EnterUpdateVoiceSource;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = 1;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 退出音源板刷字库的数据填充
        /// </summary>
        /// <returns></returns>
        public byte[] Display_vExitUpdateVoiceSource()
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.ExitUpdateVoiceSource;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = 1;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 更新音源板刷字库
        /// </summary>
        /// <param name="payload">音源板字库bin文件内容字节数组</param>
        /// <returns></returns>
        public byte[] Dispaly_vUpdateVoiceSource(byte[] payload, int actualLength = 224)
        {
            byte[] send_cmd = new byte[actualLength + 6];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.UpdateVoiceSource;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = (byte)actualLength;
            Buffer.BlockCopy(payload, 0, send_cmd, 4, actualLength);
            send_cmd[^2] = Check_Sum_Cal(send_cmd);
            send_cmd[^1] = ProductCommunicate_Struct.FrameFailure;

            return send_cmd;
        }
        /// <summary>
        /// 更改通讯波特率
        /// </summary>
        /// <param name="data">0,1,2,3,4,5: 4800,9600,19200,57600,115200,460800</param>
        /// <returns></returns>
        public byte[] Dispaly_vResetCommunicateBaudRate(byte data)
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.ResetProductBaudrate;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = data;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 播放/暂停录音
        /// </summary>
        /// <param name="data">01播放；00 暂停</param>
        /// <returns></returns>
        public byte[] Dispaly_vDisplay_Redio(byte data)
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Display_Redio;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = data;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 删除录音
        /// </summary>
        /// <returns></returns>
        public byte[] Dispaly_vDelete_Redio()
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Delete_Redio;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = 0;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 调节监听音量
        /// </summary>
        /// <param name="data">01: 调大; 00: 调小</param>
        /// <returns></returns>
        public byte[] Dispaly_Adjust_MornitorVolume(byte data)
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Adjust_MornitorVolume;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = data;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        /// <summary>
        /// 查询话筒状态数据填充
        /// </summary>
        /// <returns></returns>
        public byte[] Dispaly_QueryMicroPhoneStatus()
        {
            byte[] send_cmd = new byte[7];
            send_cmd[0] = ProductCommunicate_Struct.FrameHeader;
            send_cmd[1] = (byte)ProductCommunicate_Struct.ProductCmd.Query_MicroPhoneStatus;
            send_cmd[2] = (byte)(~send_cmd[1]);
            send_cmd[3] = 1;
            send_cmd[4] = 0;
            send_cmd[5] = Check_Sum_Cal(send_cmd);
            send_cmd[6] = ProductCommunicate_Struct.FrameFailure;
            return send_cmd;
        }
        #endregion
    }
}
